package com.zhiyu.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.tomcat.util.codec.binary.Base64;

import javafx.util.Pair;

public class RSAUtil {
    /**
     * 用rsa生成公钥私钥对
     *
     * @return 公钥私钥对
     * @throws NoSuchAlgorithmException
     */
    public static Pair<String, String> generateKeyPair() throws NoSuchAlgorithmException {
        // keyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥生成器，密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对，保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();

        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

        // 得到成base64编码的公钥字符串
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到成base64编码的私钥字符串
        String privateKeyString = new String(Base64.encodeBase64(privateKey.getEncoded()));

        return new Pair<String, String>(publicKeyString, privateKeyString);
    }

    /**
     * 加密，将传入公钥字符串生成rsa公钥对象，加密待加密的内容 加密过程：待加密字符串->待加密字节数组->加密后的字节数组->base64编码的加密字符串
     *
     * @param content 将要被加密的内容 publicKey 公钥字符串
     * @return 加密后的字符串
     * @throws Exception
     */
    public static String encrypt(String content, String publicKeyString) throws Exception {
        byte[] decoded = Base64.decodeBase64(publicKeyString);
        RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(decoded));

        // RSA密码器，用来执行加密
        Cipher cipher = Cipher.getInstance("RSA");
        // 初始化密码器，第一个参数指定加密模式，第二个参数指定公钥
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] contentBytes = content.getBytes("utf-8");
        String encryptedContent = Base64.encodeBase64String(cipher.doFinal(contentBytes));

        return encryptedContent;
    }

    /**
     * 解密，将传入的私钥字符串生成rsa私钥对象，解密待解密的字符串
     * 解码过程：base64编码的加密字符串->加密后的字节数组->解密后的字节数组->解密后的字符串
     *
     * @param encryptedStr 待解密的内容 privateKeyString 私钥字符串
     * @return 解密后的内容
     * @throws Exception
     */
    public static String decrypt(String encryptedStr, String privateKeyString) throws Exception {
        byte[] decoded = Base64.decodeBase64(privateKeyString);

        RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
                .generatePrivate(new PKCS8EncodedKeySpec(decoded));

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] encryptedByte = Base64.decodeBase64(encryptedStr.getBytes("utf-8"));
        String decryptedContent = new String(cipher.doFinal(encryptedByte));

        return decryptedContent;
    }
}
